<?php

class relocator extends Module {
	
	private
		$lockItems = array (
			'.',
			'..',
			'.svn',
			'.cache',
			'.settings',
			'.project',
			'install.zip'
		);
	
	public function __construct () {
		parent::__construct (__CLASS__);
	}
	
	public function __default () {
		$response = new ModuleResponse;
		$response->setTemplate ('relocator/index');
		return $response;
	}
	
	public function build () {
		$this->expectSecureGET ();
		
		include ENGINE_ROOT . '/libs/pclzip.lib.php';
		
		$mainZipFile = DOC_ROOT . '/site.zip';
		$filesZipFile = ENGINE_ROOT . '/temp/install.zip';
		$mysqlDumpFile = ENGINE_ROOT . '/temp/dump.sql';
		
		if (file_exists ($mainZipFile)) {
			unlink ($mainZipFile);
		}
		if (file_exists ($filesZipFile)) {
			unlink ($filesZipFile);
		}
		
		$mainZip = new PclZip ($mainZipFile);
		$filesZip = new PclZip ($filesZipFile);
		
		$this->readFiles ('', $filesZip);
		
		$mainZip->create ($filesZipFile, PCLZIP_OPT_REMOVE_PATH, ENGINE_ROOT . '/temp');
		
		$this->buildMySQLDump ($mysqlDumpFile);
		
		$mainZip->add ($mysqlDumpFile, PCLZIP_OPT_REMOVE_PATH, ENGINE_ROOT . '/temp');
		$mainZip->add (ENGINE_ROOT . '/modules/relocator/install.php', PCLZIP_OPT_REMOVE_PATH, ENGINE_ROOT . '/modules/relocator');
		$mainZip->add (ENGINE_ROOT . '/libs/pclzip.lib.php', PCLZIP_OPT_REMOVE_PATH, ENGINE_ROOT . '/libs');
		
		unlink ($filesZipFile);
		unlink ($mysqlDumpFile);
		
		redirect (HTTP_HOST . '/site.zip');
	}
	
	private function readFiles ($relDir, PclZip $zip) {
		$list = scandir (DOC_ROOT . '/' . $relDir);
		
		foreach ($list as $item) {
			$itemRelPath = $relDir . ($relDir != '' ? '/' : '') . trim ($item, '/');
			$itemFullPath = DOC_ROOT . '/' . $itemRelPath;
					
			if (in_array ($item, $this->lockItems)) {
				continue;
			}
			
			if (is_dir ($itemFullPath)) {
				$this->readFiles ($itemRelPath, $zip);
			} else {
				$zip->add ($itemFullPath, PCLZIP_OPT_REMOVE_PATH, DOC_ROOT);
			}
		}
	}
	
	private function buildMySQLDump ($filePath) {
		$db = DBController::getInstance ();
		
		$str = <<<TEXT
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

TEXT;
		
		$getTables = $db->query ("SHOW TABLES FROM `" . DB_NAME . "`");
		$aQueries = array ();
		
		while (list ($tableName) = $db->fetch_row ($getTables)) {
			$str .= "DROP TABLE IF EXISTS `" . $tableName . "`;\n";
			$this->getTableDump ($tableName, &$aQueries);
		}
		
		foreach ($aQueries['tables'] as $tableDump) {
			$str .= $tableDump;
		}
		
		foreach ($aQueries['values'] as $valuesDump) {
			$str .= $valuesDump;
		}
		
		$str .= <<<TEXT
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
TEXT;
		
		$file = fopen ($filePath, 'w+');
		fwrite ($file, $str);
		fclose ($file);
	}

	private function getTableDump ($tableName, &$aQueries) {
		$db = DBController::getInstance ();
		
		$getCreate = $db->query ("SHOW CREATE TABLE `" . DB_NAME . "`.`" . $tableName . "`");
		list (,$strCreate) = $db->fetch_row ($getCreate);
		$strCreate = str_replace ("\n", " ", $strCreate);	
		
		$getStatus = $db->query ("SHOW TABLE STATUS FROM `" . DB_NAME . "` WHERE Name = '" . $tableName . "'");
		$aStatus = $db->fetch_array ($getStatus);
		
		$aQueries['tables'][] = $strCreate . ' AUTO_INCREMENT=' . $aStatus['Auto_increment'] . ";\n";
		
		
		$sInsert = '';
		
		if ($aStatus['Rows'] > 0) {
			$sInsert = 'INSERT INTO `' . $tableName . '` (';
			
			$getCols = $db->query ("SHOW COLUMNS FROM `" . DB_NAME . "`.`" . $tableName . "`");
			$aCols = array ();
			
			while ($col = $db->fetch_array ($getCols)) {
				$aCols[] = '`' . $col['Field'] . '`';
			}
			
			$sInsert .= implode (', ', $aCols) . ') VALUES ';
			
			$getValues = $db->query ("SELECT * FROM `" . DB_NAME . "`.`" . $tableName . "`");
			$aValues = array ();
			
			while ($row = $db->fetch_array ($getValues)) {
				$aRowValues = array ();
				
				foreach ($row as $fieldValue) {
					if ($fieldValue === NULL) {
						$aRowValues[] = 'NULL';
					} else {				
						$fieldValue = str_replace ('\'', '\'\'', $fieldValue);
						$fieldValue = str_replace ("\n", "\\n", $fieldValue);
						$fieldValue = str_replace ("\r", "\\r", $fieldValue);
						$fieldValue = str_replace ("\t", "\\t", $fieldValue);
						$aRowValues[] = '\'' . $fieldValue . '\'';
					}
				}
				
				$aValues[] = "(" . implode(', ', $aRowValues) . ')';
			}
			
			$sInsert .= implode (', ', $aValues) . ";\n";
			
			$aQueries['values'][] = $sInsert;
		}		
	}
	
}